package com.retailcloud.searchservice.utils;

import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpHost;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortBuilder;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;

public class ElasticsearchClientUtil {

    private static final Logger logger = LoggerFactory.getLogger(ElasticsearchClientUtil.class);

    private static final String ES_HOST = "10.211.55.22";
    private static final int ES_PORT = 9200;
    private static final String ES_SCHEME = "http";

    private static volatile RestHighLevelClient client;
    private static final Object lock = new Object();

    private ElasticsearchClientUtil() {}

    public static RestHighLevelClient getClient() {
        if (client == null) {
            synchronized (lock) {
                if (client == null) {
                    client = new RestHighLevelClient(
                            RestClient.builder(new HttpHost(ES_HOST, ES_PORT, ES_SCHEME))
                    );
                }
            }
        }
        return client;
    }

    /**
     * 执行带有 search_after 分页的查询
     *
     * @param index 索引名称
     * @param query 查询条件
     * @param sort  排序条件
     * @param page  当前页码
     * @param size  每页大小
     * @param searchAfter 上一页的最后一个排序值
     * @return 查询结果
     * @throws IOException 如果查询失败
     */
    public static SearchResponse searchWithPaging(String index, BoolQueryBuilder query, SortBuilder<?> sort, int page, int size,String searchAfter) throws IOException {
        RestHighLevelClient restHighLevelClient = getClient();

        SearchRequest searchRequest = new SearchRequest(index);
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

        // 设置查询条件
        searchSourceBuilder.query(query);

        // 设置排序
        searchSourceBuilder.sort(sort);

        // 设置分页参数
        searchSourceBuilder.size(size);

        // 设置 from 参数
        if (page == 1 || StringUtils.isBlank(searchAfter) ) {
            searchSourceBuilder.from(0);
        } else {
            Object[] searchAfterArray = new Object[]{searchAfter};
            searchSourceBuilder.from(0); // 当使用 search_after 时，from 必须设置为 0
            searchSourceBuilder.searchAfter(searchAfterArray);
        }

        // 设置搜索请求的搜索源
        searchRequest.source(searchSourceBuilder);

        // 执行查询
        return restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
    }

    /**
     * 关闭 RestHighLevelClient
     */
    public static void closeClient() {
        if (client != null) {
            try {
                client.close();
            } catch (IOException e) {
                logger.error("Failed to close Elasticsearch client", e);
            } finally {
                client = null;
            }
        }
    }

    /**
     * 获取下一页的 search_after 值
     *
     * @param searchResponse 查询响应
     * @return 下一页的 search_after 值
     */
    /**
     * 获取下一页的 search_after 值
     *
     * @param searchResponse 查询响应
     * @return 下一页的 search_after 值
     */
    public static String getNextSearchAfter(SearchResponse searchResponse) {
        String nextSearchAfter = null;
        if (searchResponse.getHits().getHits().length > 0) {
            Object sortValuesObj = searchResponse.getHits().getHits()[searchResponse.getHits().getHits().length - 1].getSortValues();
            Object[] objects = (Object[]) sortValuesObj;

            return String.valueOf(objects[0]);
        }
        return nextSearchAfter;

    }
}
